﻿using System.Xml.Linq;
using K9Nano.Extensions;
using K9Nano.Settings;
using Microsoft.EntityFrameworkCore;

namespace K9Nano.Domain.Settings;

public abstract class SettingStoreBase<TDbContext>(TDbContext db) : ISettingStore
    where TDbContext : DbContext
{
    protected TDbContext Db { get; } = db;

    public virtual async Task CreateOrUpdateAsync(SettingInfo setting, CancellationToken cancellation = default)
    {
        var query = Db.Set<AppSetting>().AsNoTracking()
            .Where(a => a.Name == setting.Name && a.UserId == setting.UserId);
        var entity = await query.FirstOrDefaultAsync(cancellation);
        if (entity is null)
        {
            entity = new AppSetting
            {
                Name = setting.Name,
                Value = setting.Value
            };
            Db.Add(entity);
        }
        else
        {
            entity.Value = setting.Value;
        }

        await Db.SaveChangesAsync(cancellation);
    }

    public virtual async Task DeleteAsync(SettingInfo setting, CancellationToken cancellation = default)
    {
        var query = Db.Set<AppSetting>().AsNoTracking()
           .Where(a => a.Name == setting.Name && a.UserId == setting.UserId);
        var entity = await query.FirstOrDefaultAsync(cancellation);
        if (entity is null) return;
        Db.Remove(entity);
        await Db.SaveChangesAsync(cancellation);
    }

    public virtual async Task<IReadOnlyList<SettingInfo>> GetAllListAsync(long? userId, CancellationToken cancellation = default)
    {
        var query = Db.Set<AppSetting>().AsNoTracking().Where(a => a.UserId == userId);
        var result = await query
            .Select(a => new SettingInfo
            {
                UserId = userId,
                Name = a.Name,
                Value = a.Value
            })
           .ToListAsync(cancellation);
        return result;
    }

    public virtual async Task<SettingInfo?> GetSettingOrNullAsync(long? userId, string name, CancellationToken cancellation = default)
    {
        var query = Db.Set<AppSetting>().AsNoTracking().Where(a => a.Name == name && a.UserId == userId);
        var result = await query
            .Select(a => new SettingInfo
            {
                UserId = userId,
                Name = a.Name,
                Value = a.Value
            })
            .FirstOrDefaultAsync(cancellation);
        return result;
    }
}